package com.cy.ppj.comm.interceptor;

import com.cy.ppj.comm.constant.Constants;
import com.cy.ppj.comm.exception.MsgException;
import com.cy.ppj.model.dto.manager.ManagerLoginDTO;
import com.cy.ppj.service.rule.RuleService;
import com.cy.ppj.model.domian.rule.Menu;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Component;
import org.springframework.util.AntPathMatcher;
import org.springframework.util.StringUtils;
import org.springframework.web.servlet.HandlerInterceptor;
import org.springframework.web.servlet.ModelAndView;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.util.List;
import java.util.Optional;

/**
 * @description: 管理员登录拦截器
 * @author: Ocean
 * @create: 2018-07-23 17:03
 **/
@Slf4j
@Component
public class AdminLoginInterceptor implements HandlerInterceptor {

    @Autowired
    private RedisTemplate redisTemplate;
    @Autowired
    private RuleService ruleService;

    private AntPathMatcher antPathMatcher = new AntPathMatcher();

    @Override
    public boolean preHandle(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o) throws Exception {
        //从头部获取token
        String token = httpServletRequest.getHeader(Constants.TOKEN);
        if (StringUtils.isEmpty(token)) {
            throw new MsgException("未登录", -1000);
        }
        String key = Constants.ADMIN_LOGIN_KEY.concat(token);
        //查询是否存在
        Object obj = redisTemplate.opsForValue().get(key);
        if (obj == null) {
            throw new MsgException("登录已失效", -1000);
        }
        //重新设置过期时间
        redisTemplate.expire(key, Constants.LOGIN_TIME, Constants.LOGIN_TIME_UNIT);

        ManagerLoginDTO managerLoginDTO = (ManagerLoginDTO) obj;

        //查看该角色是否有权限
        boolean hasRole = hasRole(httpServletRequest, managerLoginDTO);
        if (!hasRole) {
            throw new MsgException("权限不足");
        }

        return true;
    }

    private boolean hasRole(HttpServletRequest httpServletRequest, ManagerLoginDTO managerLoginDTO) {

        if (Constants.ADMININTRATOR.equals(managerLoginDTO.getRoleId())) {
            //超级管理员权限
            return true;
        }

        String uri = httpServletRequest.getRequestURI();

        //查询缓存中的菜单
        List<Menu> menus = ruleService.queryMenuPatternInCache();

        Optional<Menu> optional = menus.stream()
                .filter(m -> StringUtils.hasLength(m.getPattern()))
                .filter(m -> antPathMatcher.match(m.getPattern(), uri)).findFirst();
        if (!optional.isPresent()) {
            //如果uri未配置菜单，则返回true
            return true;
        }
        //该路径菜单
        Menu menu = optional.get();
        //用户角色
        Long roleId = managerLoginDTO.getRoleId();
        //该角色下所有的路径ID
        List<Long> menuIds = ruleService.queryMenuIdInCahe(roleId);
        if (menuIds.isEmpty()) {
                return false;
        }

        return menuIds.stream().anyMatch(id -> id.equals(menu.getId()));
    }

    @Override
    public void postHandle(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o, ModelAndView modelAndView) throws Exception {

    }

    @Override
    public void afterCompletion(HttpServletRequest httpServletRequest, HttpServletResponse httpServletResponse, Object o, Exception e) throws Exception {

    }
}
